package com.skynet.supervision.utils;

import cn.hutool.core.collection.CollectionUtil;
import cn.hutool.core.text.StrFormatter;
import com.skynet.supervision.common.ErrCode;
import com.skynet.supervision.common.Result;
import com.skynet.supervision.exceptions.CheckedException;
import lombok.val;
import org.springframework.lang.Nullable;
import org.springframework.validation.BindException;
import org.springframework.validation.BindingResult;
import org.springframework.validation.FieldError;

import javax.validation.ConstraintViolation;
import javax.validation.constraints.NotNull;
import java.util.List;
import java.util.Objects;
import java.util.Set;
import java.util.stream.Collectors;
import java.util.stream.StreamSupport;

public class Errors {

    public static final int EBAD_PARAMS = -2000;

    public static @Nullable
    CheckedException wrapValidateException(@NotNull BindException e) {
        if (e == null || !e.hasErrors()) {
            return null;
        }
        return wrapValidateException(e.getBindingResult());
    }

    public static @Nullable <T> CheckedException wrapValidateException(@NotNull Set<ConstraintViolation<T>> constraintViolations) {
        if (CollectionUtil.isEmpty(constraintViolations)) {
            return null;
        }
        final String errorMessages = constraintViolations.stream().map(it -> {
            val lastNode =
                    StreamSupport.stream(it.getPropertyPath().spliterator(), false)
                            .reduce((l, r) -> r).orElse(null);
            return StrFormatter.format("{} : {}",
                    Objects.requireNonNull(lastNode).getName(),
                    it.getMessage());
        }).collect(Collectors.joining(","));

        return Result.failure()
                .withCode(EBAD_PARAMS)
                .withMessage(Strings.sprintf("请求参数错误,{}", errorMessages)).wrap();
    }


    public static @Nullable
    CheckedException wrapValidateException(BindingResult result) {
        if (result == null) {
            return null;
        }
        List<FieldError> fieldErrors = result.getFieldErrors();
        if (CollectionUtil.isEmpty(fieldErrors)) {
            return null;
        }
        val errorMessages = fieldErrors.stream()
                .map(it -> StrFormatter.format("{} : {}", it.getField(), it.getDefaultMessage()))
                .collect(Collectors.joining(","));
        return Result.failure()
                .withCode(EBAD_PARAMS)
                .withMessage(Strings.sprintf("请求参数错误,{}", errorMessages)).wrap();
    }

    public static Result wrapException(int code,Exception ex) {
        if (ex instanceof CheckedException) {
            CheckedException be = (CheckedException) ex;
            return be.unwrap();
        } else {
            return Result.newResult(code, getRootCause(ex).getMessage());
        }
    }
    public static Result wrapException(ErrCode code,Exception ex) {
        if (ex instanceof CheckedException) {
            CheckedException be = (CheckedException) ex;
            return be.unwrap();
        } else {
            return Result.newResult(code, getRootCause(ex).toString());
        }
    }


    public static Throwable getRootCause(Throwable t) {
        if (t == null || t.getCause() == null) {
            return t;
        }
        return getRootCause(t.getCause());
    }

    public static CheckedException notImplementException() {
        return Result.failure(ErrCode.NOT_IMPL_YET).withMessage("该方法未实现").wrap();
    }
}
